<template>
  <div class="zeus-cascader"
       ref="cascader"
       v-click-outside="close">
    <div class="zeus-cascader-trigger"
         @click="toggle">
      {{ result || '&nbsp;' }}
    </div>
    <div class="zeus-cascader-popover"
         v-if="popoverVisible">
      <CascaderItems :height="popoverHeight"
                     :loadData="loadData"
                     :selected="selected"
                     :loadingItem="loadingItem"
                     @update:selected="onUpdateSelected"
                     @update:colse="close"
                     :source="dataSource" />
    </div>
  </div>
</template>

<script lang="ts">
import { ref, computed, Ref, reactive } from "vue";
import CascaderItems from "./CascaderItems.vue";
import ClickOutside from "./click-outside";
export default {
  components: {
    CascaderItems,
  },
  directives: { ClickOutside },
  props: {
    dataSource: {
      type: Array,
    },
    popoverHeight: {
      type: String,
      default: '200px'
    },
    selected: {
      type: Array,
      default: () => [],
    },
    loadData: {
      type: Function,
    },
  },
  setup(props, context) {
    let popoverVisible = ref(false);
    let cascader = ref<HTMLDivElement>(null);
    // 加载的数据
    let loadingItem = ref({});

    const close = () => {
      popoverVisible.value = false;
    };

    const toggle = () => {
      popoverVisible.value = !popoverVisible.value;
    };

    // 当数据为最后一个children
    const simplest = (children, id) => {
      return children.value.filter((item) => item.id === id)[0];
    };

    // 当数据不是最后一个children
    const complex = (children, id) => {
      let noChildren = ref([]);
      let hasChildren = ref([]);

      children.forEach((item) => {
        item.children
          ? hasChildren.value.push(item)
          : noChildren.value.push(item);
      });
      let found = simplest(noChildren, id);
      if (found) {
        return found;
      } else {
        found = simplest(hasChildren, id);
        if (found) {
          return found;
        } else {
          for (let i = 0; i < hasChildren.value.length; i++) {
            found = complex(hasChildren.value[i].children, id);
            if (found) {
              return found;
            }
          }
          return undefined;
        }
      }
    };

    const onUpdateSelected = (newSelected) => {
      context.emit("update:selected", newSelected);
      let lastItem = newSelected[newSelected.length - 1];
      let updateSource = (result) => {
        loadingItem.value = {};
        const copy = JSON.parse(JSON.stringify(props.dataSource));
        let toUpdate = complex(copy, lastItem.id);
        toUpdate.children = result;
        context.emit("update:dataSource", copy);
      };
      if (!lastItem.isLeaf && props.loadData) {
        props.loadData(lastItem, updateSource);
        loadingItem.value = lastItem;
      }
    };

    // 展示用户选中的数据
    const result = computed(() => {
      return props.selected.map((item) => item.name).join("/");
    });

    return {
      popoverVisible,
      result,
      onUpdateSelected,
      cascader,
      toggle,
      close,
      loadingItem,
    };
  },
};
</script>

<style lang="scss">
.zeus-cascader {
  position: relative;
  display: inline-block;
  &-trigger {
    height: 32px;
    min-width: 10em;
    border: 1px solid #999;
    border-radius: 4px;
    padding: 0 1em;
    display: inline-flex;
    align-items: center;
  }

  &-popover {
    position: absolute;
    top: 100%;
    left: 0;
    background: #fff;
    display: flex;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
    margin-top: 8px;
    z-index: 1;
  }
}
</style>
